package game.manager;

import game.Event;
import game.screen.Screen;
import game.screen.option.ScreenOption;
import game.util.Util;

import java.util.List;
import java.util.Observable;
import java.util.Scanner;

public class InputManager implements Manager {
	private Scanner console;

	private static InputManager manager;

	public static InputManager getManager() {
		if (manager == null)
			manager = new InputManager();
		return manager;
	}

	private InputManager() {
		this.initialize();
	}

	@Override
	public void gameUpdate() {
	}

	private String nextLine(String query) {
		Util.print(query + "> ");
		return this.console.nextLine();
	}

	public String getStringInput(String query) {
		String input = nextLine(query);
		ScreenManager.getManager().getActiveScreen().refreshScreen();
		return input;
	}

	public void selectFromOptions(final List<ScreenOption> options) {
		final Runnable runnable = new Runnable() {
			@Override
			public void run() {
				boolean selectionMade = false;
				String stringChoice = "";
				// Prompt until a valid selection is made
				while (!selectionMade) {
					try {
						// Read a line of text from the user
						stringChoice = InputManager.this.nextLine("");
						// Parse that text into a choice number
						final int choice = Integer.parseInt(stringChoice) - 1;
						// If the choice is valid
						if (choice >= 0 && choice < options.size()) {
							final ScreenOption option = options.get(choice);
							if (option.isEnabled()) {
								// Select the choice
								selectionMade = true;
								option.select();
							}
						} else {
							selectionMade = true;
							Screen activeScreen = ScreenManager.getManager()
									.getActiveScreen();
							ScreenManager.getManager().activateScreen(
									activeScreen);
						}
					} catch (NumberFormatException e) {
						Util.print("Invalid input received: " + stringChoice
								+ ", expected number\n");
					}
				}
			}
		};
		Thread worker = new Thread(runnable);
		worker.start();
	}

	@Override
	public void update(Observable o, Object arg) {
		final Event event = (Event) arg;

		switch (event.getType()) {
		case RESET:
			this.initialize();
			break;
		}
	}

	@Override
	public void initialize() {
		if (this.console == null)
			this.console = new Scanner(System.in);
		this.console.reset();
	}
}
